Digital Twin Zoo Dashboard

CCTV

กล้องภายในอาคาร (110 ตัว)
108 ใช้งานได้
2 เสีย
กล้องภายนอกอาคาร (336 ตัว)
334 ใช้งานได้
2 เสีย

Access Control

ควบคุมและบันทึกการเข้าออกของบุคลากรและผู้เข้าชม

Animal Chart

CCTV คอกสัตว์ ตรวจนับจำนวนสัตว์อัตโนมัติ

BMS - พลังงานรวม

BMS - HVAC

BMS - ปั๊มน้ำ

BMS - แสงสว่าง

IoT - Temperature

IoT - PM2.5

จำนวนจุดตรวจวัด: 20 จุด

IoT - AQI

จำนวนจุดตรวจวัด: 20 จุด

Visitor (Weekly)

รายได้จากการขายตั๋ว (บาท/สัปดาห์): 75,600

Energy by Zone

Public Zone: PA, PB1, PB2, Food Court, Car Park Building, คอกสัตว์
Service Zone: SA, SP, SG

Water Usage Ratio

Visitor App Usage

/**************************************************** * Chart.js Section * ****************************************************/ // CCTV Bar Chart const cctvBarCtx = document.getElementById('cctvBarChart').getContext('2d'); new Chart(cctvBarCtx, { type: 'bar', data: { labels: ['กล้องภายในอาคาร', 'กล้องภายนอกอาคาร'], datasets: [ { label: 'ใช้งานได้', data: [108, 334], backgroundColor: getComputedStyle(document.documentElement).getPropertyValue('--sec-americano') }, { label: 'เสีย', data: [2, 2], backgroundColor: getComputedStyle(document.documentElement).getPropertyValue('--sec-redwine') } ] }, options: { responsive: true, plugins: { title: { display: true, text: 'สถานะกล้องวงจรปิดแยกตามตำแหน่ง' }, legend: { position: 'bottom' } }, scales: { x: { stacked: true }, y: { beginAtZero: true, stacked: true, suggestedMax: 350 } } } }); // CCTV Pie Chart const cctvPieCtx = document.getElementById('cctvPieChart').getContext('2d'); new Chart(cctvPieCtx, { type: 'pie', data: { labels: ['ใช้งานได้', 'เสีย'], datasets: [{ data: [108+334, 2+2], backgroundColor: [ getComputedStyle(document.documentElement).getPropertyValue('--sec-americano'), getComputedStyle(document.documentElement).getPropertyValue('--sec-redwine') ] }] }, options: { responsive: true, plugins: { title: { display: true, text: 'สรุปสถานะกล้องวงจรปิด (รวมทุกตำแหน่ง)' }, legend: { position: 'bottom' } } } }); // Access Control Chart const accessControlCtx = document.getElementById('accessControlChart').getContext('2d'); new Chart(accessControlCtx, { type: 'pie', data: { labels: ['Visitor', 'Staff', 'Maintenance'], datasets: [{ data: [70, 20, 10], backgroundColor: [ getComputedStyle(document.documentElement).getPropertyValue('--sec-apricot'), getComputedStyle(document.documentElement).getPropertyValue('--primary-forest'), getComputedStyle(document.documentElement).getPropertyValue('--sec-coralpink') ], borderWidth: 1 }] }, options: { responsive: true, plugins: { title: { display: true, text: 'สัดส่วนการเข้าออก' }, legend: { position: 'bottom' } } } }); // Animal Chart const animalLabels = [ 'ช้างเอเชีย', 'นกกระเรียนพันธุ์ไทย', 'แรดขาว', 'ไฮยีน่าลายจุด', 'ฮิปโปโปเตมัส', 'สิงโต', 'ลิงชิมแปนซี', 'นกแก้วเทาแอฟริกัน', 'เก้ง', 'ควายน้ำ' ]; const animalData = [3, 7, 2, 5, 4, 2, 6, 8, 10, 4]; const animalCtx = document.getElementById('animalChart').getContext('2d'); new Chart(animalCtx, { type: 'bar', data: { labels: animalLabels, datasets: [{ label: 'จำนวนสัตว์', data: animalData, backgroundColor: getComputedStyle(document.documentElement).getPropertyValue('--primary-forest') }] }, options: { responsive: true, plugins: { title: { display: true, text: 'จำนวนสัตว์ในแต่ละประเภท (ตรวจนับด้วย CCTV)' } }, scales: { y: { beginAtZero: true, suggestedMax: 12 } } } }); // BMS Chart const bmsCtx = document.getElementById('bmsChart').getContext('2d'); new Chart(bmsCtx, { type: 'bar', data: { labels: ['Lighting', 'HVAC', 'Pumps', 'Other'], datasets: [{ label: 'การใช้พลังงาน (kWh)', data: [150, 300, 200, 100], backgroundColor: getComputedStyle(document.documentElement).getPropertyValue('--primary-gold') }] }, options: { responsive: true, plugins: { title: { display: true, text: 'การใช้พลังงานในระบบ BMS' } }, scales: { y: { beginAtZero: true } } } }); // BMS - HVAC Chart const bmsHVACCtx = document.getElementById('bmsHVACChart').getContext('2d'); new Chart(bmsHVACCtx, { type: 'line', data: { labels: ['00:00','04:00','08:00','12:00','16:00','20:00'], datasets: [{ label: 'HVAC (kWh)', data: [50,70,100,120,90,60], borderColor: getComputedStyle(document.documentElement).getPropertyValue('--sec-apricot'), backgroundColor: 'rgba(241, 191, 80, 0.2)', fill: true, tension: 0.3 }] }, options: { responsive: true, plugins: { title: { display: true, text: 'การใช้พลังงาน HVAC' } }, scales: { y: { beginAtZero: true } } } }); // BMS - Water Chart const bmsWaterCtx = document.getElementById('bmsWaterChart').getContext('2d'); new Chart(bmsWaterCtx, { type: 'line', data: { labels: ['00:00','04:00','08:00','12:00','16:00','20:00'], datasets: [{ label: 'น้ำ (m³)', data: [30,45,50,55,40,35], borderColor: getComputedStyle(document.documentElement).getPropertyValue('--sec-americano'), backgroundColor: 'rgba(132, 193, 155, 0.2)', fill: true, tension: 0.3 }] }, options: { responsive: true, plugins: { title: { display: true, text: 'การใช้น้ำของปั๊มน้ำ' } }, scales: { y: { beginAtZero: true } } } }); // BMS - Lighting Chart const bmsLightingCtx = document.getElementById('bmsLightingChart').getContext('2d'); new Chart(bmsLightingCtx, { type: 'doughnut', data: { labels: ['Indoor', 'Outdoor'], datasets: [{ data: [65, 35], backgroundColor: [ getComputedStyle(document.documentElement).getPropertyValue('--primary-forest'), getComputedStyle(document.documentElement).getPropertyValue('--sec-salmon') ] }] }, options: { responsive: true, plugins: { title: { display: true, text: 'การใช้พลังงานแสงสว่าง' }, legend: { position: 'bottom' } } } }); // IoT - Temperature Chart const iotSensorCtx = document.getElementById('iotSensorChart').getContext('2d'); new Chart(iotSensorCtx, { type: 'line', data: { labels: ['06:00','09:00','12:00','15:00','18:00','21:00'], datasets: [{ label: 'อุณหภูมิ (°C)', data: [22,24,27,26,23,21], borderColor: getComputedStyle(document.documentElement).getPropertyValue('--sec-salmon'), backgroundColor: 'rgba(217,116,83,0.2)', fill: true, tension: 0.3 }] }, options: { responsive: true, plugins: { title: { display: true, text: 'การวัดอุณหภูมิจากเซ็นเซอร์' } }, scales: { y: { beginAtZero: false } } } }); // IoT - PM2.5 Chart const pm25Ctx = document.getElementById('pm25Chart').getContext('2d'); new Chart(pm25Ctx, { type: 'line', data: { labels: ['06:00','09:00','12:00','15:00','18:00','21:00'], datasets: [{ label: 'PM2.5 (µg/m³)', data: [35,40,38,42,45,39], borderColor: getComputedStyle(document.documentElement).getPropertyValue('--sec-redwine'), backgroundColor: 'rgba(118,32,42,0.2)', fill: true, tension: 0.3 }] }, options: { responsive: true, plugins: { title: { display: true, text: 'PM2.5 ระดับฝุ่น (20 จุด)' } }, scales: { y: { beginAtZero: true } } } }); // IoT - AQI Chart const aqiCtx = document.getElementById('aqiChart').getContext('2d'); new Chart(aqiCtx, { type: 'line', data: { labels: ['06:00','09:00','12:00','15:00','18:00','21:00'], datasets: [{ label: 'AQI', data: [80,90,85,95,100,88], borderColor: getComputedStyle(document.documentElement).getPropertyValue('--primary-forest'), backgroundColor: 'rgba(57,100,67,0.2)', fill: true, tension: 0.3 }] }, options: { responsive: true, plugins: { title: { display: true, text: 'ค่า AQI (20 จุด)' } }, scales: { y: { beginAtZero: true } } } }); // Visitor Chart const visitorData = [120,150,180,170,200,230,210]; const ticketIncome = visitorData.reduce((sum, n) => sum + n, 0) * 60; // สมมติราคาตั๋ว 60 บาท/คน document.getElementById('ticketIncomeValue').textContent = ticketIncome.toLocaleString(); const visitorCtx = document.getElementById('visitorChart').getContext('2d'); new Chart(visitorCtx, { type: 'line', data: { labels: ['จันทร์','อังคาร','พุธ','พฤหัสบดี','ศุกร์','เสาร์','อาทิตย์'], datasets: [{ label: 'จำนวนผู้เข้าชม', data: visitorData, borderColor: getComputedStyle(document.documentElement).getPropertyValue('--sec-americano'), backgroundColor: 'rgba(132,193,155,0.2)', fill: true, tension: 0.3 }] }, options: { responsive: true, plugins: { title: { display: true, text: 'จำนวนผู้เข้าชมรายสัปดาห์' } }, scales: { y: { beginAtZero: true } } } }); // Energy by Zone Chart const publicZoneLabels = ['PA', 'PB1', 'PB2', 'Food Court', 'Car Park Building', 'คอกสัตว์']; const serviceZoneLabels = ['SA', 'SP', 'SG']; const publicZoneData = [120, 100, 95, 130, 80, 140]; const serviceZoneData = [60, 75, 55]; const energyZoneCtx = document.getElementById('energyZoneChart').getContext('2d'); new Chart(energyZoneCtx, { type: 'bar', data: { labels: [...publicZoneLabels, ...serviceZoneLabels], datasets: [ { label: 'Public Zone', data: [...publicZoneData, ...Array(serviceZoneLabels.length).fill(null)], backgroundColor: getComputedStyle(document.documentElement).getPropertyValue('--sec-apricot') }, { label: 'Service Zone', data: [...Array(publicZoneLabels.length).fill(null), ...serviceZoneData], backgroundColor: getComputedStyle(document.documentElement).getPropertyValue('--sec-coralpink') } ] }, options: { responsive: true, plugins: { title: { display: true, text: 'การใช้พลังงานรายอาคาร (แยก Zone)' }, legend: { position: 'bottom' } }, scales: { x: { stacked: true }, y: { beginAtZero: true, stacked: true } } } }); // Water Usage Ratio Chart const waterCtx = document.getElementById('waterChart').getContext('2d'); new Chart(waterCtx, { type: 'pie', data: { labels: ['การใช้น้ำในระบบ','รีไซเคิลน้ำ','น้ำที่สูญเสีย'], datasets: [{ data: [60,30,10], backgroundColor: [ getComputedStyle(document.documentElement).getPropertyValue('--sec-apricot'), getComputedStyle(document.documentElement).getPropertyValue('--sec-americano'), getComputedStyle(document.documentElement).getPropertyValue('--sec-redwine') ] }] }, options: { responsive: true, plugins: { title: { display: true, text: 'สัดส่วนการใช้น้ำ' }, legend: { position: 'bottom' } } } }); // Visitor App Usage Chart const visitorAppCtx = document.getElementById('visitorAppChart').getContext('2d'); new Chart(visitorAppCtx, { type: 'doughnut', data: { labels: ['Map','Ticket','Promotions','Other'], datasets: [{ data: [40,30,20,10], backgroundColor: [ getComputedStyle(document.documentElement).getPropertyValue('--primary-forest'), getComputedStyle(document.documentElement).getPropertyValue('--sec-apricot'), getComputedStyle(document.documentElement).getPropertyValue('--sec-coralpink'), getComputedStyle(document.documentElement).getPropertyValue('--sec-salmon') ] }] }, options: { responsive: true, plugins: { title: { display: true, text: 'การใช้งานแอปผู้เข้าชม' }, legend: { position: 'bottom' } } } }); /**************************************************** * Chart.js Section * ****************************************************/ // 1) CCTV - แยกกลุ่ม กล้องภายใน/ภายนอก/สถานะ // ข้อมูล: ภายใน 108 ปกติ, 2 เสีย | ภายนอก 334 ปกติ, 2 เสีย // CCTV Bar Chart: stacked (2 group, 2 status) const cctvBarCtx = document.getElementById('cctvBarChart').getContext('2d'); new Chart(cctvBarCtx, { type: 'bar', data: { labels: ['กล้องภายในอาคาร', 'กล้องภายนอกอาคาร'], datasets: [ { label: 'ใช้งานได้', data: [108, 334], backgroundColor: getComputedStyle(document.documentElement).getPropertyValue('--sec-americano') }, { label: 'เสีย', data: [2, 2], backgroundColor: getComputedStyle(document.documentElement).getPropertyValue('--sec-redwine') } ] }, options: { responsive: true, plugins: { title: { display: true, text: 'สถานะกล้องวงจรปิดแยกตามตำแหน่ง' }, legend: { position: 'bottom' } }, scales: { x: { stacked: true }, y: { beginAtZero: true, stacked: true, suggestedMax: 350 } } } }); // CCTV Pie Chart: รวมทั้ง 2 กลุ่ม const cctvPieCtx = document.getElementById('cctvPieChart').getContext('2d'); new Chart(cctvPieCtx, { type: 'pie', data: { labels: ['ใช้งานได้', 'เสีย'], datasets: [{ data: [108+334, 2+2], backgroundColor: [ getComputedStyle(document.documentElement).getPropertyValue('--sec-americano'), getComputedStyle(document.documentElement).getPropertyValue('--sec-redwine') ] }] }, options: { responsive: true, plugins: { title: { display: true, text: 'สรุปสถานะกล้องวงจรปิด (รวมทุกตำแหน่ง)' }, legend: { position: 'bottom' } } } }); // 2) Access Control - Pie Chart (เหมือนเดิม) const accessControlCtx = document.getElementById('accessControlChart').getContext('2d'); new Chart(accessControlCtx, { type: 'pie', data: { labels: ['Visitor', 'Staff', 'Maintenance'], datasets: [{ data: [70, 20, 10], backgroundColor: [ getComputedStyle(document.documentElement).getPropertyValue('--sec-apricot'), getComputedStyle(document.documentElement).getPropertyValue('--primary-forest'), getComputedStyle(document.documentElement).getPropertyValue('--sec-coralpink') ], borderWidth: 1 }] }, options: { responsive: true, plugins: { title: { display: true, text: 'สัดส่วนการเข้าออก' }, legend: { position: 'bottom' } } } }); // 3) Animal Chart - เพิ่ม 10 ชนิดสัตว์ const animalLabels = [ 'ช้างเอเชีย', 'นกกระเรียนพันธุ์ไทย', 'แรดขาว', 'ไฮยีน่าลายจุด', 'ฮิปโปโปเตมัส', 'สิงโต', 'ลิงชิมแปนซี', 'นกแก้วเทาแอฟริกัน', 'เก้ง', 'ควายน้ำ' ]; // จำนวนสัตว์ (ตัวอย่าง) const animalData = [3, 7, 2, 5, 4, 2, 6, 8, 10, 4]; const animalCtx = document.getElementById('animalChart').getContext('2d'); new Chart(animalCtx, { type: 'bar', data: { labels: animalLabels, datasets: [{ label: 'จำนวนสัตว์', data: animalData, backgroundColor: getComputedStyle(document.documentElement).getPropertyValue('--primary-forest') }] }, options: { responsive: true, plugins: { title: { display: true, text: 'จำนวนสัตว์ในแต่ละประเภท (ตรวจนับด้วย CCTV)' } }, scales: { y: { beginAtZero: true, suggestedMax: 12 } } } }); // 4) BMS - พลังงานรวม (Bar) const bmsCtx = document.getElementById('bmsChart').getContext('2d'); new Chart(bmsCtx, { type: 'bar', data: { labels: ['Lighting', 'HVAC', 'Pumps', 'Other'], datasets: [{ label: 'การใช้พลังงาน (kWh)', data: [150, 300, 200, 100], backgroundColor: getComputedStyle(document.documentElement).getPropertyValue('--primary-gold') }] }, options: { responsive: true, plugins: { title: { display: true, text: 'การใช้พลังงานในระบบ BMS' } }, scales: { y: { beginAtZero: true } } } }); // 5) BMS - HVAC (Line) const bmsHVACCtx = document.getElementById('bmsHVACChart').getContext('2d'); new Chart(bmsHVACCtx, { type: 'line', data: { labels: ['00:00','04:00','08:00','12:00','16:00','20:00'], datasets: [{ label: 'HVAC (kWh)', data: [50,70,100,120,90,60], borderColor: getComputedStyle(document.documentElement).getPropertyValue('--sec-apricot'), backgroundColor: 'rgba(241, 191, 80, 0.2)', fill: true, tension: 0.3 }] }, options: { responsive: true, plugins: { title: { display: true, text: 'การใช้พลังงาน HVAC' } }, scales: { y: { beginAtZero: true } } } }); // 6) BMS - ปั๊มน้ำ (Line) const bmsWaterCtx = document.getElementById('bmsWaterChart').getContext('2d'); new Chart(bmsWaterCtx, { type: 'line', data: { labels: ['00:00','04:00','08:00','12:00','16:00','20:00'], datasets: [{ label: 'น้ำ (m³)', data: [30,45,50,55,40,35], borderColor: getComputedStyle(document.documentElement).getPropertyValue('--sec-americano'), backgroundColor: 'rgba(132, 193, 155, 0.2)', fill: true, tension: 0.3 }] }, options: { responsive: true, plugins: { title: { display: true, text: 'การใช้น้ำของปั๊มน้ำ' } }, scales: { y: { beginAtZero: true } } } }); // 7) BMS - แสงสว่าง (Doughnut) const bmsLightingCtx = document.getElementById('bmsLightingChart').getContext('2d'); new Chart(bmsLightingCtx, { type: 'doughnut', data: { labels: ['Indoor', 'Outdoor'], datasets: [{ data: [65, 35], backgroundColor: [ getComputedStyle(document.documentElement).getPropertyValue('--primary-forest'), getComputedStyle(document.documentElement).getPropertyValue('--sec-salmon') ] }] }, options: { responsive: true, plugins: { title: { display: true, text: 'การใช้พลังงานแสงสว่าง' }, legend: { position: 'bottom' } } } }); // 8) IoT - Temperature (Line) const iotSensorCtx = document.getElementById('iotSensorChart').getContext('2d'); new Chart(iotSensorCtx, { type: 'line', data: { labels: ['06:00','09:00','12:00','15:00','18:00','21:00'], datasets: [{ label: 'อุณหภูมิ (°C)', data: [22,24,27,26,23,21], borderColor: getComputedStyle(document.documentElement).getPropertyValue('--sec-salmon'), backgroundColor: 'rgba(217,116,83,0.2)', fill: true, tension: 0.3 }] }, options: { responsive: true, plugins: { title: { display: true, text: 'การวัดอุณหภูมิจากเซ็นเซอร์' } }, scales: { y: { beginAtZero: false } } } }); // 9) IoT - PM2.5 (Line) - เพิ่มระบุ 20 จุด const pm25Ctx = document.getElementById('pm25Chart').getContext('2d'); new Chart(pm25Ctx, { type: 'line', data: { labels: ['06:00','09:00','12:00','15:00','18:00','21:00'], datasets: [{ label: 'PM2.5 (µg/m³)', data: [35,40,38,42,45,39], borderColor: getComputedStyle(document.documentElement).getPropertyValue('--sec-redwine'), backgroundColor: 'rgba(118,32,42,0.2)', fill: true, tension: 0.3 }] }, options: { responsive: true, plugins: { title: { display: true, text: 'PM2.5 ระดับฝุ่น (20 จุด)' } }, scales: { y: { beginAtZero: true } } } }); // 10) IoT - AQI (Line) - เพิ่มระบุ 20 จุด const aqiCtx = document.getElementById('aqiChart').getContext('2d'); new Chart(aqiCtx, { type: 'line', data: { labels: ['06:00','09:00','12:00','15:00','18:00','21:00'], datasets: [{ label: 'AQI', data: [80,90,85,95,100,88], borderColor: getComputedStyle(document.documentElement).getPropertyValue('--primary-forest'), backgroundColor: 'rgba(57,100,67,0.2)', fill: true, tension: 0.3 }] }, options: { responsive: true, plugins: { title: { display: true, text: 'ค่า AQI (20 จุด)' } }, scales: { y: { beginAtZero: true } } } }); // 11) Analytics - Visitor Chart (Line) const visitorData = [120,150,180,170,200,230,210]; const ticketIncome = visitorData.reduce((sum, n) => sum + n, 0) * 60; // สมมติราคาตั๋ว 60 บาท/คน document.getElementById('ticketIncomeValue').textContent = ticketIncome.toLocaleString(); const visitorCtx = document.getElementById('visitorChart').getContext('2d'); new Chart(visitorCtx, { type: 'line', data: { labels: ['จันทร์','อังคาร','พุธ','พฤหัสบดี','ศุกร์','เสาร์','อาทิตย์'], datasets: [{ label: 'จำนวนผู้เข้าชม', data: visitorData, borderColor: getComputedStyle(document.documentElement).getPropertyValue('--sec-americano'), backgroundColor: 'rgba(132,193,155,0.2)', fill: true, tension: 0.3 }] }, options: { responsive: true, plugins: { title: { display: true, text: 'จำนวนผู้เข้าชมรายสัปดาห์' } }, scales: { y: { beginAtZero: true } } } }); // ====== Energy by Zone: Public/Service Zone ====== const publicZoneLabels = ['PA', 'PB1', 'PB2', 'Food Court', 'Car Park Building', 'คอกสัตว์']; const serviceZoneLabels = ['SA', 'SP', 'SG']; const publicZoneData = [120, 100, 95, 130, 80, 140]; const serviceZoneData = [60, 75, 55]; const energyZoneCtx = document.getElementById('energyZoneChart').getContext('2d'); new Chart(energyZoneCtx, { type: 'bar', data: { labels: [...publicZoneLabels, ...serviceZoneLabels], datasets: [ { label: 'Public Zone', data: [...publicZoneData, ...Array(serviceZoneLabels.length).fill(null)], backgroundColor: getComputedStyle(document.documentElement).getPropertyValue('--sec-apricot') }, { label: 'Service Zone', data: [...Array(publicZoneLabels.length).fill(null), ...serviceZoneData], backgroundColor: getComputedStyle(document.documentElement).getPropertyValue('--sec-coralpink') } ] }, options: { responsive: true, plugins: { title: { display: true, text: 'การใช้พลังงานรายอาคาร (แยก Zone)' }, legend: { position: 'bottom' } }, scales: { x: { stacked: true }, y: { beginAtZero: true, stacked: true } } } }); // 13) Analytics - Water Usage Ratio (Pie) const waterCtx = document.getElementById('waterChart').getContext('2d'); new Chart(waterCtx, { type: 'pie', data: { labels: ['การใช้น้ำในระบบ','รีไซเคิลน้ำ','น้ำที่สูญเสีย'], datasets: [{ data: [60,30,10], backgroundColor: [ getComputedStyle(document.documentElement).getPropertyValue('--sec-apricot'), getComputedStyle(document.documentElement).getPropertyValue('--sec-americano'), getComputedStyle(document.documentElement).getPropertyValue('--sec-redwine') ] }] }, options: { responsive: true, plugins: { title: { display: true, text: 'สัดส่วนการใช้น้ำ' }, legend: { position: 'bottom' } } } }); // 14) Analytics - Visitor App Usage (Doughnut) const visitorAppCtx = document.getElementById('visitorAppChart').getContext('2d'); new Chart(visitorAppCtx, { type: 'doughnut', data: { labels: ['Map','Ticket','Promotions','Other'], datasets: [{ data: [40,30,20,10], backgroundColor: [ getComputedStyle(document.documentElement).getPropertyValue('--primary-forest'), getComputedStyle(document.documentElement).getPropertyValue('--sec-apricot'), getComputedStyle(document.documentElement).getPropertyValue('--sec-coralpink'), getComputedStyle(document.documentElement).getPropertyValue('--sec-salmon') ] }] }, options: { responsive: true, plugins: { title: { display: true, text: 'การใช้งานแอปผู้เข้าชม' }, legend: { position: 'bottom' } } } });